use crate::collector::{MetricsCollector, MetricFamily, MetricType, MetricValue, Labels};
use async_trait::async_trait;
use rustcloud_core::{ServiceResult, ServiceError};
use std::collections::HashMap;
use std::fmt::Write;
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};
use tokio::sync::RwLock;

/// Prometheus指标导出器
pub struct PrometheusExporter {
    collector: Arc<dyn MetricsCollector>,
    registry: Arc<RwLock<PrometheusRegistry>>,
}

impl PrometheusExporter {
    pub fn new(collector: Arc<dyn MetricsCollector>) -> Self {
        Self {
            collector,
            registry: Arc::new(RwLock::new(PrometheusRegistry::new())),
        }
    }

    /// 导出为Prometheus文本格式
    pub async fn export(&self) -> ServiceResult<String> {
        let metric_families = self.collector.gather().await?;
        let mut output = String::new();

        for family in metric_families {
            self.write_metric_family(&mut output, &family)?;
        }

        Ok(output)
    }

    /// 导出到HTTP响应
    pub async fn export_http(&self) -> ServiceResult<(String, String)> {
        let body = self.export().await?;
        let content_type = "text/plain; version=0.0.4; charset=utf-8".to_string();
        Ok((content_type, body))
    }

    /// 收集指标数据
    pub async fn gather(&self) -> ServiceResult<Vec<MetricFamily>> {
        self.collector.gather().await
    }

    /// 写入指标族
    fn write_metric_family(&self, output: &mut String, family: &MetricFamily) -> ServiceResult<()> {
        if family.metrics.is_empty() {
            return Ok(());
        }

        // 写入HELP注释
        if !family.help.is_empty() {
            writeln!(output, "# HELP {} {}", family.name, escape_help(&family.help))
                .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
        }

        // 写入TYPE注释
        let prometheus_type = match family.metric_type {
            MetricType::Counter => "counter",
            MetricType::Gauge => "gauge",
            MetricType::Histogram => "histogram",
            MetricType::Summary => "summary",
        };
        writeln!(output, "# TYPE {} {}", family.name, prometheus_type)
            .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;

        // 写入指标数据
        for metric in &family.metrics {
            self.write_metric(output, metric)?;
        }

        Ok(())
    }

    /// 写入单个指标
    fn write_metric(&self, output: &mut String, metric: &crate::collector::Metric) -> ServiceResult<()> {
        let timestamp = metric.timestamp
            .duration_since(UNIX_EPOCH)
            .unwrap_or_default()
            .as_millis();

        match &metric.value {
            MetricValue::Counter(value) => {
                writeln!(
                    output,
                    "{}{} {} {}",
                    metric.name,
                    format_labels(&metric.labels),
                    value,
                    timestamp
                )
                .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
            }
            MetricValue::Gauge(value) => {
                writeln!(
                    output,
                    "{}{} {} {}",
                    metric.name,
                    format_labels(&metric.labels),
                    value,
                    timestamp
                )
                .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
            }
            MetricValue::Histogram { count, sum, buckets } => {
                // 写入每个桶
                for (upper_bound, bucket_count) in buckets {
                    let mut bucket_labels = metric.labels.clone();
                    bucket_labels.insert("le".to_string(), upper_bound.to_string());
                    writeln!(
                        output,
                        "{}_bucket{} {} {}",
                        metric.name,
                        format_labels(&bucket_labels),
                        bucket_count,
                        timestamp
                    )
                    .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
                }

                // 写入总数
                writeln!(
                    output,
                    "{}_count{} {} {}",
                    metric.name,
                    format_labels(&metric.labels),
                    count,
                    timestamp
                )
                .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;

                // 写入总和
                writeln!(
                    output,
                    "{}_sum{} {} {}",
                    metric.name,
                    format_labels(&metric.labels),
                    sum,
                    timestamp
                )
                .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
            }
            MetricValue::Summary { count, sum, quantiles } => {
                // 写入分位数
                for (quantile, value) in quantiles {
                    let mut quantile_labels = metric.labels.clone();
                    quantile_labels.insert("quantile".to_string(), quantile.to_string());
                    writeln!(
                        output,
                        "{}{} {} {}",
                        metric.name,
                        format_labels(&quantile_labels),
                        value,
                        timestamp
                    )
                    .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
                }

                // 写入总数
                writeln!(
                    output,
                    "{}_count{} {} {}",
                    metric.name,
                    format_labels(&metric.labels),
                    count,
                    timestamp
                )
                .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;

                // 写入总和
                writeln!(
                    output,
                    "{}_sum{} {} {}",
                    metric.name,
                    format_labels(&metric.labels),
                    sum,
                    timestamp
                )
                .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
            }
        }

        Ok(())
    }
}

/// Prometheus注册表
pub struct PrometheusRegistry {
    metrics: HashMap<String, Box<dyn PrometheusMetric + Send + Sync>>,
}

impl PrometheusRegistry {
    pub fn new() -> Self {
        Self {
            metrics: HashMap::new(),
        }
    }

    pub fn register(&mut self, name: String, metric: Box<dyn PrometheusMetric + Send + Sync>) {
        self.metrics.insert(name, metric);
    }

    pub fn unregister(&mut self, name: &str) -> bool {
        self.metrics.remove(name).is_some()
    }

    pub async fn gather(&self) -> ServiceResult<Vec<MetricFamily>> {
        let mut families = Vec::new();
        for metric in self.metrics.values() {
            families.extend(metric.collect().await?);
        }
        Ok(families)
    }
}

/// Prometheus指标trait
#[async_trait]
pub trait PrometheusMetric {
    async fn collect(&self) -> ServiceResult<Vec<MetricFamily>>;
    fn describe(&self) -> Vec<MetricDescription>;
}

/// 指标描述
#[derive(Debug, Clone)]
pub struct MetricDescription {
    pub name: String,
    pub help: String,
    pub metric_type: MetricType,
    pub constant_labels: Labels,
}

impl MetricDescription {
    pub fn new(name: String, help: String, metric_type: MetricType) -> Self {
        Self {
            name,
            help,
            metric_type,
            constant_labels: HashMap::new(),
        }
    }

    pub fn with_constant_labels(mut self, labels: Labels) -> Self {
        self.constant_labels = labels;
        self
    }
}

/// 便利的指标具送器
pub struct PrometheusCounterVec {
    name: String,
    help: String,
    label_names: Vec<String>,
    metrics: Arc<RwLock<HashMap<String, f64>>>,
}

impl PrometheusCounterVec {
    pub fn new(name: String, help: String, label_names: Vec<String>) -> Self {
        Self {
            name,
            help,
            label_names,
            metrics: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    pub async fn with_label_values(&self, label_values: &[&str]) -> ServiceResult<PrometheusCounter> {
        if label_values.len() != self.label_names.len() {
            return Err(ServiceError::MetricsError(
                "Label values count mismatch".to_string()
            ));
        }

        let labels: Labels = self.label_names
            .iter()
            .zip(label_values.iter())
            .map(|(name, value)| (name.clone(), value.to_string()))
            .collect();

        let key = format_labels(&labels);
        Ok(PrometheusCounter {
            name: self.name.clone(),
            labels,
            key,
            metrics: self.metrics.clone(),
        })
    }
}

#[async_trait]
impl PrometheusMetric for PrometheusCounterVec {
    async fn collect(&self) -> ServiceResult<Vec<MetricFamily>> {
        let metrics_map = self.metrics.read().await;
        let mut metrics = Vec::new();

        for (key, value) in metrics_map.iter() {
            let labels = parse_labels(key);
            metrics.push(crate::collector::Metric::new(
                self.name.clone(),
                self.help.clone(),
                MetricType::Counter,
                MetricValue::Counter(*value),
            ).with_labels(labels));
        }

        Ok(vec![MetricFamily {
            name: self.name.clone(),
            help: self.help.clone(),
            metric_type: MetricType::Counter,
            metrics,
        }])
    }

    fn describe(&self) -> Vec<MetricDescription> {
        vec![MetricDescription::new(
            self.name.clone(),
            self.help.clone(),
            MetricType::Counter,
        )]
    }
}

/// 单个计数器
pub struct PrometheusCounter {
    name: String,
    labels: Labels,
    key: String,
    metrics: Arc<RwLock<HashMap<String, f64>>>,
}

impl PrometheusCounter {
    pub async fn inc(&self) -> ServiceResult<()> {
        self.inc_by(1.0).await
    }

    pub async fn inc_by(&self, value: f64) -> ServiceResult<()> {
        if value < 0.0 {
            return Err(ServiceError::MetricsError(
                "Counter value cannot be negative".to_string()
            ));
        }

        let mut metrics = self.metrics.write().await;
        *metrics.entry(self.key.clone()).or_insert(0.0) += value;
        Ok(())
    }

    pub async fn get(&self) -> f64 {
        let metrics = self.metrics.read().await;
        *metrics.get(&self.key).unwrap_or(&0.0)
    }
}

/// 格式化标签为 Prometheus 格式
fn format_labels(labels: &Labels) -> String {
    if labels.is_empty() {
        return String::new();
    }

    let mut sorted_labels: Vec<_> = labels.iter().collect();
    sorted_labels.sort_by_key(|&(k, _)| k);

    let mut result = String::from("{");
    for (i, (key, value)) in sorted_labels.iter().enumerate() {
        if i > 0 {
            result.push(',');
        }
        write!(result, "{}=\"{}\"", key, escape_label_value(value)).unwrap();
    }
    result.push('}');
    result
}

/// 解析标签字符串
fn parse_labels(labels_str: &str) -> Labels {
    let mut labels = HashMap::new();
    if labels_str.is_empty() || labels_str == "{}" {
        return labels;
    }

    let content = labels_str.trim_start_matches('{').trim_end_matches('}');
    for pair in content.split(',') {
        match pair.split_once('=') {
            Some((key, value)) => {
                let value = value.trim_matches('"');
                labels.insert(key.to_string(), value.to_string());
            }
            None => {}
        }
    }
    labels
}

/// 转义help文本
fn escape_help(help: &str) -> String {
    help.replace('\\', "\\\\")
        .replace('\n', "\\n")
}

/// 转义标签值
fn escape_label_value(value: &str) -> String {
    value.replace('\\', "\\\\")
        .replace('"', "\\\"")
        .replace('\n', "\\n")
        .replace('\t', "\\t")
}

/// 创建默认的Prometheus注册表
pub fn default_registry() -> Arc<RwLock<PrometheusRegistry>> {
    Arc::new(RwLock::new(PrometheusRegistry::new()))
}

/// 创建计数器向量
pub fn new_counter_vec(name: &str, help: &str, label_names: &[&str]) -> PrometheusCounterVec {
    PrometheusCounterVec::new(
        name.to_string(),
        help.to_string(),
        label_names.iter().map(|s| s.to_string()).collect(),
    )
}

/// HTTP 服务器用于导出Prometheus指标
pub struct PrometheusHttpServer {
    exporter: PrometheusExporter,
    port: u16,
    path: String,
}

impl PrometheusHttpServer {
    pub fn new(exporter: PrometheusExporter, port: u16) -> Self {
        Self {
            exporter,
            port,
            path: "/metrics".to_string(),
        }
    }

    pub fn with_path(mut self, path: String) -> Self {
        self.path = path;
        self
    }

    /// 启动HTTP服务器（简化实现）
    pub async fn start(&self) -> ServiceResult<()> {
        // 这里可以集成真实的HTTP服务器，比如axum、warp等
        // 目前只提供接口定义
        Ok(())
    }

    /// 处理指标请求
    pub async fn handle_metrics(&self) -> ServiceResult<(String, String)> {
        self.exporter.export_http().await
    }
}

/// 常用的系统指标收集器
pub struct SystemMetricsCollector {
    process_metrics: Arc<RwLock<HashMap<String, f64>>>,
}

impl SystemMetricsCollector {
    pub fn new() -> Self {
        Self {
            process_metrics: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    /// 收集进程指标
    pub async fn collect_process_metrics(&self) -> ServiceResult<()> {
        let mut metrics = self.process_metrics.write().await;
        
        // 这里可以集成真实的系统指标收集
        // 比如CPU使用率、内存使用率、文件描述符数量等
        metrics.insert("process_cpu_seconds_total".to_string(), 0.0);
        metrics.insert("process_resident_memory_bytes".to_string(), 0.0);
        metrics.insert("process_open_fds".to_string(), 0.0);
        
        Ok(())
    }
}

#[async_trait]
impl PrometheusMetric for SystemMetricsCollector {
    async fn collect(&self) -> ServiceResult<Vec<MetricFamily>> {
        let metrics = self.process_metrics.read().await;
        let mut families = Vec::new();
        
        for (name, value) in metrics.iter() {
            let metric_type = if name.contains("_total") {
                MetricType::Counter
            } else {
                MetricType::Gauge
            };
            
            families.push(MetricFamily {
                name: name.clone(),
                help: format!("System metric: {}", name),
                metric_type: metric_type.clone(),
                metrics: vec![crate::collector::Metric::new(
                    name.clone(),
                    format!("System metric: {}", name),
                    metric_type,
                    if name.contains("_total") {
                        MetricValue::Counter(*value)
                    } else {
                        MetricValue::Gauge(*value)
                    },
                )],
            });
        }
        
        Ok(families)
    }

    fn describe(&self) -> Vec<MetricDescription> {
        vec![
            MetricDescription::new(
                "process_cpu_seconds_total".to_string(),
                "Total user and system CPU time spent in seconds".to_string(),
                MetricType::Counter,
            ),
            MetricDescription::new(
                "process_resident_memory_bytes".to_string(),
                "Resident memory size in bytes".to_string(),
                MetricType::Gauge,
            ),
            MetricDescription::new(
                "process_open_fds".to_string(),
                "Number of open file descriptors".to_string(),
                MetricType::Gauge,
            ),
        ]
    }
}

impl Default for SystemMetricsCollector {
    fn default() -> Self {
        Self::new()
    }
}